package com.qc.sys.controller;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.captcha.ShearCaptcha;
import cn.hutool.captcha.generator.RandomGenerator;
import com.qc.sys.common.*;
import com.qc.sys.entity.SysLoginfo;
import com.qc.sys.entity.SysMenu;
import com.qc.sys.entity.SysUser;
import com.qc.sys.service.SysLoginfoService;
import com.qc.sys.service.SysMenuService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Controller
@RequestMapping("login")
public class LoginController {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Resource
    private SysMenuService menuService;

    @Autowired
    private SysLoginfoService loginfoService;

    /**
     * 用户登录
     * */
    @ResponseBody
    @PostMapping("/doLogin")
    public ResultObj doLogin(String loginname, String password,String keyCode,String captcha, HttpServletRequest request){
        try {
            //redis取出验证码
            ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
            String code = opsForValue.get(keyCode);
            if (null==code){
                return new ResultObj(-1,"验证码过期");
            }else {
                if (code.equalsIgnoreCase(captcha)){
                    Subject subject = SecurityUtils.getSubject();
                    UsernamePasswordToken passwordToken = new UsernamePasswordToken(loginname,password);
                    subject.login(passwordToken);
                    //得到shiro的sessionId
                    String token = subject.getSession().getId().toString();
                    //写入登录日志
                    ActiveUser activeUser = (ActiveUser) subject.getPrincipal();
                    SysUser user = activeUser.getUser();
                    SysLoginfo loginfo = new SysLoginfo();
                    loginfo.setLoginip(request.getRemoteAddr());
                    loginfo.setLoginname(user.getName()+'-'+user.getLoginname());
                    loginfo.setLogintime(new Date());
                    loginfoService.save(loginfo);
                    List<String> permissions = activeUser.getPermissions();
                    Map<String, Object> map = new HashMap<>();
                    map.put("token",token);
                    map.put("permissions",permissions);
                    map.put("usertype",user.getType());
                    map.put("username",user.getName());
                    return new ResultObj(200,"登录成功",map);
                }else {
                    return new ResultObj(-1,"验证码不正确");
                }
            }
        } catch (AuthenticationException e) {
            e.printStackTrace();
            return new ResultObj(-1,"用户或密码不正确");
        }
    }

    /**
     * 加载所有菜单[顶部，左侧]
     * */
    @ResponseBody
    @GetMapping("loadIndexMenu")
    public Object loadIndexMenu(){
        //1.得到当前登录的用户
        Subject subject = SecurityUtils.getSubject();
        ActiveUser activeUser = (ActiveUser) subject.getPrincipal();
        SysUser user = activeUser.getUser();
        if (null==user){
            return null;
        }
        //2.对用户进行类型判断
        List<SysMenu> menus = null;
        if (user.getType().equals(Constant.USER_TYPE_SUPER)){ //超级管理员
            menus= menuService.queryAllMenuForList();
        }else{
            menus= menuService.queryAllMenuForListByUserId(user.getId());
        }

        List<TreeNode> treeNodes = new ArrayList<>();
        for (SysMenu menu : menus) {
            Boolean spread = menu.getSpread()==Constant.SPREAD_TRUE?true:false;
            treeNodes.add(new TreeNode(menu.getId(),menu.getPid(),menu.getTitle(),menu.getIcon(),menu.getHref(),spread,menu.getTarget(),menu.getTypecode()));
        }
        List<TreeNode> nodes = TreeNodeBuilder.build(treeNodes, 0);
        Map<String, Object> map = new HashMap<>();
        for (TreeNode n : nodes) {
            map.put(n.getTypecode(),n);
        }
        return map;
    }

    /**
     * 验证当前token是否登录
     * */
    @ResponseBody
    @PostMapping("checkLogin")
    public ResultObj checkLogin(){
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()){
            return ResultObj.IS_LOGIN;
        }else{
            return ResultObj.UN_LOGIN;
        }
    }

    /**
     * 验证码
     *  1.打开页面，请求后台给验证码的图片，前端生产一个随机字符串带出去
     *  2.下次登录UUID和验证码带过去
     *
     * redis key value
     * */
    @GetMapping("captcha")
    public void captcha(HttpServletResponse response,String codeKey) throws IOException {
        //定义图形验证码的长、宽、验证码字符数、干扰线宽度
        ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(100, 38, 4, 4);
        String code = captcha.getCode();
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        opsForValue.set(codeKey,code);
        opsForValue.getOperations().expire(codeKey,60, TimeUnit.SECONDS);
        //图形验证码写出，可以写出到文件，也可以写出到流
        captcha.write(response.getOutputStream());
    }


}
